/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处，作者声明等。
4.分发源码时候，请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名，模块名称，项目代码等时，请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点，可申请商业授权，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.facedoor.modular.devicebase.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import vip.xiaonuo.core.context.constant.ConstantContextHolder;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.DateUtils;
import vip.xiaonuo.core.util.PoiUtil;
import vip.xiaonuo.facedoor.iservice.IDeviceBaseService;
import vip.xiaonuo.facedoor.modular.device.entity.DeviceCategory;
import vip.xiaonuo.facedoor.modular.device.listener.DeviceChangeTypeEnum;
import vip.xiaonuo.facedoor.modular.device.listener.DevicePublisher;
import vip.xiaonuo.facedoor.modular.device.listener.DeviceSourceEnum;
import vip.xiaonuo.facedoor.modular.devicebase.entity.DeviceBase;
import vip.xiaonuo.facedoor.modular.devicebase.enums.DeviceBaseExceptionEnum;
import vip.xiaonuo.facedoor.modular.devicebase.mapper.DeviceBaseMapper;
import vip.xiaonuo.facedoor.modular.devicebase.param.DeviceBaseParam;
import vip.xiaonuo.facedoor.modular.devicebase.param.LockerPersonImportBean;
import vip.xiaonuo.facedoor.modular.devicebase.service.DeviceBaseService;
import vip.xiaonuo.facedoor.modular.devicebase.vo.lock.LockCell;
import vip.xiaonuo.facedoor.modular.devicebase.vo.lock.LockCellState;
import vip.xiaonuo.facedoor.modular.devicebase.vo.StatisticsVo;
import vip.xiaonuo.facedoor.modular.devicehistory.entity.DeviceHistory;
import vip.xiaonuo.facedoor.modular.devicehistory.service.DeviceHistoryService;
import vip.xiaonuo.facedoor.modular.deviceset.entity.DwDeviceSet;
import vip.xiaonuo.facedoor.modular.deviceset.service.DwDeviceSetService;
import vip.xiaonuo.facedoor.modular.idcardhistory.entity.IdCardHistory;
import vip.xiaonuo.facedoor.modular.idcardhistory.service.IdCardHistoryService;
import vip.xiaonuo.facedoor.modular.memberdevice.entity.MemberDevice;
import vip.xiaonuo.facedoor.modular.memberdevice.service.MemberDeviceService;
import vip.xiaonuo.facedoor.modular.memberdevice.service.impl.MemberDeviceServiceImpl;
import vip.xiaonuo.facedoor.modular.memberuser.entity.MemberUser;
import vip.xiaonuo.facedoor.modular.memberuser.service.MemberUserService;
import vip.xiaonuo.facedoor.modular.memberuser.vo.MemberImportResultPojoVO;
import vip.xiaonuo.facedoor.modular.memberuser.vo.UserImportResultVO;
import vip.xiaonuo.facedoor.modular.visitorhistory.entity.VisitorHistory;
import vip.xiaonuo.facedoor.modular.visitorhistory.service.VisitorHistoryService;
import vip.xiaonuo.facedoor.rule.DeviceTypeRuleService;
import vip.xiaonuo.facedoor.rule.DwRulesEngine;
import vip.xiaonuo.facedoor.rule.HQRulesEngine;
import vip.xiaonuo.facedoor.rule.VeinRulesEngine;
import vip.xiaonuo.facedoor.vo.dewo.GetPersonResponse;
import vip.xiaonuo.sys.modular.file.enums.FileTypeEnum;
import vip.xiaonuo.sys.modular.file.service.SysFileInfoService;
import vip.xiaonuo.sys.modular.timer.entity.SysTimers;
import vip.xiaonuo.sys.modular.timer.enums.TimerJobStatusEnum;
import vip.xiaonuo.sys.modular.timer.service.SysTimersService;
import vip.xiaonuo.sys.modular.timer.service.TimerExeService;
import vip.xiaonuo.sys.modular.timer.util.TaskUtil;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 终端基础属性表service接口实现类
 *
 * @author 胡鹏达
 * @date 2022-07-08 15:24:36
 * * TODO: 代修改海清同步
 */
@Service
@Slf4j
public class DeviceBaseServiceImpl extends ServiceImpl<DeviceBaseMapper, DeviceBase> implements DeviceBaseService {


    @Autowired
    private TimerExeService timerExeService;

    @Autowired
    private SysTimersService sysTimersService;


    @Resource
    private DeviceHistoryService deviceHistoryService;

    @Resource
    private IdCardHistoryService idCardHistoryService;

    @Resource
    private VisitorHistoryService visitorHistoryService;

    @Resource
    private DwDeviceSetService dwDeviceSetService;


    @Resource
    private DevicePublisher publisher;

    @Resource
    private SysFileInfoService sysFileInfoService;

    @Resource
    private MemberUserService memberUserService;

    @Resource
    private MemberDeviceService memberDeviceService;

    //系统允许接入设备数
    public static final String CACHE_DEVICENUM = "deviceNum";

    @Override
    public StatisticsVo statistics() {

        Date dayBegin = DateUtils.getDayBegin();
        Date dayEnd = DateUtils.getDayEnd();

        StatisticsVo statisticsVo = new StatisticsVo();
        // 全部设备
        long allDeviceNum = this.count();
        statisticsVo.setDeviceNum(allDeviceNum);

        // 设备
        long onLine = this.count(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getDeviceState, 1));
        statisticsVo.setOnLineDeviceNum(onLine);
        statisticsVo.setOfflineDeviceNum(allDeviceNum - onLine);

        long deviceTemperatureNum = deviceHistoryService.count(new LambdaQueryWrapper<DeviceHistory>().isNotNull(DeviceHistory::getTemperature)
                .between(DeviceHistory::getDeviceCurrentDate, dayBegin, dayEnd));
        statisticsVo.setDeviceTemperatureNum(deviceTemperatureNum);

        long visitorTemperatureNum = visitorHistoryService.count(new LambdaQueryWrapper<VisitorHistory>().isNotNull(VisitorHistory::getTemperature)
                .between(VisitorHistory::getDeviceCurrentDate, dayBegin, dayEnd));
        statisticsVo.setVisitorTemperatureNum(visitorTemperatureNum);

        long idCardTemperatureNum = idCardHistoryService.count(new LambdaQueryWrapper<IdCardHistory>().isNotNull(IdCardHistory::getTemperature)
                .between(IdCardHistory::getComparedDate, dayBegin, dayEnd));
        statisticsVo.setIdCardTemperatureNum(idCardTemperatureNum);

        statisticsVo.setTemperatureNum(deviceTemperatureNum + visitorTemperatureNum + idCardTemperatureNum);

        long idCardHistoryNum = idCardHistoryService.count(new LambdaQueryWrapper<IdCardHistory>().between(IdCardHistory::getComparedDate, dayBegin, dayEnd));
        statisticsVo.setIdCardHistoryNum(idCardHistoryNum);

        long greenCodeNum = idCardHistoryService.count(new LambdaQueryWrapper<IdCardHistory>().eq(IdCardHistory::getHealthColor, "1")
                .between(IdCardHistory::getComparedDate, dayBegin, dayEnd));
        statisticsVo.setGreenCodeNum(greenCodeNum);

        long yellowCodeNum = idCardHistoryService.count(new LambdaQueryWrapper<IdCardHistory>().eq(IdCardHistory::getHealthColor, "2")
                .between(IdCardHistory::getComparedDate, dayBegin, dayEnd));
        statisticsVo.setYellowCodeNum(yellowCodeNum);

        long redCodeNum = idCardHistoryService.count(new LambdaQueryWrapper<IdCardHistory>().eq(IdCardHistory::getHealthColor, "3")
                .between(IdCardHistory::getComparedDate, dayBegin, dayEnd));
        statisticsVo.setRedCodeNum(redCodeNum);

        return statisticsVo;
    }

    @Override
    public PageResult<DeviceBase> page(DeviceBaseParam deviceBaseParam) {
        QueryWrapper<DeviceBase> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(deviceBaseParam)) {

            // 根据终端注册码 查询
            if (ObjectUtil.isNotEmpty(deviceBaseParam.getRegistrationCode())) {
                queryWrapper.lambda().eq(DeviceBase::getRegistrationCode, deviceBaseParam.getRegistrationCode());
            }
            // 根据设备名称 查询
            if (ObjectUtil.isNotEmpty(deviceBaseParam.getName())) {
                queryWrapper.lambda().like(DeviceBase::getName, deviceBaseParam.getName());
            }
            if (ObjectUtil.isNotEmpty(deviceBaseParam.getDeviceState())) {
                queryWrapper.lambda().eq(DeviceBase::getDeviceState, deviceBaseParam.getDeviceState());
            }
        }

        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }

    @Override
    public List<DeviceBase> list(DeviceBaseParam deviceBaseParam) {
        QueryWrapper<DeviceBase> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(deviceBaseParam.getDeviceType())){
            queryWrapper.lambda().eq(DeviceBase::getDeviceType,deviceBaseParam.getDeviceType());
        }
        return this.list(queryWrapper);
    }

    @Override
    public void add(DeviceBaseParam deviceBaseParam) {
        RBucket<Integer> bucket = SpringUtil.getBean(RedissonClient.class).getBucket(CACHE_DEVICENUM);
        if (bucket.isExists()) {
            long count = this.count();
            Integer currentDeviceDel = ConstantContextHolder.getCurrentDeviceDel();
            if (bucket.get() + currentDeviceDel - count <= 0) {
                throw new ServiceException(500, "授权数量达到上线，请联系厂家处理! 授权设备数量" + (bucket.get() + currentDeviceDel) + "      当前设备数量" + count);
            }
        }


        String registrationCode = deviceBaseParam.getRegistrationCode();
        List<DeviceBase> list = this.list(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getRegistrationCode, registrationCode));
        if (!CollectionUtils.isEmpty(list)) {
            throw new ServiceException(500, "注册码重复!");
        }

        DeviceBase deviceBase = new DeviceBase();
        BeanUtil.copyProperties(deviceBaseParam, deviceBase);
        this.save(deviceBase);
        if (!TaskUtil.executeXxlJob() && (ObjectUtil.equal(deviceBaseParam.getDeviceType(), "1")
                || ObjectUtil.equal(deviceBaseParam.getDeviceType(), "7")
                || ObjectUtil.equal(deviceBaseParam.getDeviceType(), "4")
                || ObjectUtil.equal(deviceBaseParam.getDeviceType(), "5")
        )) {
            // 新增设备定时任务
            SysTimers sysTimers = new SysTimers();
            sysTimers.setJobParams(deviceBase.getId() + "");
            sysTimers.setActionClass("vip.xiaonuo.tasks.IssuedTask");
            sysTimers.setCron("*/20 * * * * ?");
            sysTimers.setJobStatus(TimerJobStatusEnum.RUNNING.getCode());
            sysTimers.setTimerName("【 " + deviceBase.getName() + "】" + deviceBase.getId());
            sysTimers.setRemark("人员下发定时任务 每20s执行一次!");
            sysTimersService.save(sysTimers);

            deviceBase.setTaskId(sysTimers.getId());
            this.updateById(deviceBase);

            timerExeService.startTimer(sysTimers.getId().toString(), String.valueOf(sysTimers.getJobParams()), sysTimers.getCron(), sysTimers.getActionClass());
        }

        if (!TaskUtil.executeXxlJob() && ObjectUtil.equal(deviceBaseParam.getDeviceType(), DeviceCategory.SUB_TYPE_PALM + "")) {
            // 新增设备定时任务 定时与掌静脉设备通信
            SysTimers sysTimers = new SysTimers();
            sysTimers.setJobParams(deviceBase.getId() + "");
            sysTimers.setActionClass("vip.xiaonuo.vein.task.PushDataToPalmVeinDeviceTimerTask");
            sysTimers.setCron("*/20 * * * * ?");
            sysTimers.setJobStatus(TimerJobStatusEnum.RUNNING.getCode());
            sysTimers.setTimerName("掌静脉特征值下发【 " + deviceBase.getName() + "】" + deviceBase.getId());
            sysTimers.setRemark("与掌静脉设备定时通信 每20s执行一次!");
            sysTimersService.save(sysTimers);
            deviceBase.setTaskId(sysTimers.getId());
            this.updateById(deviceBase);
            timerExeService.startTimer(sysTimers.getId().toString(), String.valueOf(sysTimers.getJobParams()), sysTimers.getCron(), sysTimers.getActionClass());
        }
        publisher.publishEvent(DeviceChangeTypeEnum.ADD, DeviceSourceEnum.BASE, deviceBase);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(DeviceBaseParam deviceBaseParam) {
        DeviceBase deviceBase = this.getById(deviceBaseParam.getId());
        if (ObjectUtil.isNull(deviceBase)) {
            throw new ServiceException(DeviceBaseExceptionEnum.NOT_EXIST);
        }

        IDeviceBaseService iDeviceBaseService = DeviceTypeRuleService.getIDeviceBaseService(deviceBase.getDeviceType());
        if (iDeviceBaseService!=null){
            iDeviceBaseService.delete(deviceBaseParam);
            // 其他不下发人员不需要删除人员直接删除配置就行
        }else {
            dwDeviceSetService.remove(new LambdaQueryWrapper<DwDeviceSet>().eq(DwDeviceSet::getDeviceBaseId, deviceBase.getId()));
            this.removeById(deviceBase.getId());
        }
        publisher.publishEvent(DeviceChangeTypeEnum.DELETE, DeviceSourceEnum.BASE, deviceBase);

    }

    @Override
    public void setUserPwd(DeviceBaseParam deviceBaseParam) {

    }

    @Override
    public void setFactoryDefault(DeviceBaseParam deviceBaseParam) {

    }

    @Override
    public void setSysTime(DeviceBaseParam deviceBaseParam) {

    }

    @Override
    public void openDoor(DeviceBaseParam deviceBaseParam) {

    }

    @Override
    public LockCellState getCellState(DeviceBaseParam deviceBaseParam) {
        LockCellState result = new LockCellState();
        DeviceBase device = detail(deviceBaseParam);
        result.setMaxColNum(device.getColNum());
        result.setMaxRowNum(device.getRowNum());
        if (device.getLockCellState() != null) {
            String state = device.getLockCellState();
            if (state.startsWith("[")) {
                List<LockCell> stateList = JSON.parseArray(device.getLockCellState(), LockCell.class);
                Map<Integer, List<LockCell>> map = new LinkedHashMap<>();
                for (LockCell cellState : stateList) {
                    Integer key = cellState.getY();
                    List<LockCell> value = map.containsKey(key) ? map.get(key) : new LinkedList<>();
                    value.add(cellState);
                    map.put(key, value);
                }

                List<List<LockCell>> cells = new LinkedList<>();
                for (Integer key : map.keySet()) {
                    cells.add(map.get(key));
                }
                result.setCells(cells);
            } else {
                result.setErrMsg(state);
            }
        }
        return result;
    }


    private void addFailMessage(List<MemberImportResultPojoVO> memberImportResultPojoVos, LockerPersonImportBean
            buildingMemberRl, String failMessage, AtomicInteger failureNum) {
        MemberImportResultPojoVO memberImportResultPojoVo = new MemberImportResultPojoVO();
        memberImportResultPojoVo.setName(buildingMemberRl.getMemberJobNum()).setFailMessage(failMessage);
        memberImportResultPojoVos.add(memberImportResultPojoVo);
        failureNum.incrementAndGet();
    }

    private void signalThreadImport(List<MemberImportResultPojoVO> memberImportResultPojoVos, AtomicInteger
            successNum, AtomicInteger failureNum, List<LockerPersonImportBean> lockerPersonImportBeans) {
        for (LockerPersonImportBean importBean : lockerPersonImportBeans) {
            try {
                List<MemberUser> memberUsers = memberUserService.list(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getJobNum, importBean.getMemberJobNum()));
                if (CollectionUtils.isEmpty(memberUsers)) {
                    addFailMessage(memberImportResultPojoVos, importBean, "人员不能为空", failureNum);
                    continue;
                }

                DeviceBase deviceBase = this.getOne(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getRegistrationCode, importBean.getRegisterCode()));
                if (deviceBase == null) {
                    addFailMessage(memberImportResultPojoVos, importBean, "找不到设备!" + importBean.getRegisterCode(), failureNum);
                    continue;
                }

                if (ObjectUtil.isNull(deviceBase.getMaxUseNum())) {
                    addFailMessage(memberImportResultPojoVos, importBean, "设备未设置最大使用人数!" + importBean.getRegisterCode(), failureNum);
                    continue;
                }

                if (StringUtils.isBlank(importBean.getLockerData())) {
                    addFailMessage(memberImportResultPojoVos, importBean, "未设置格口号!" + importBean.getRegisterCode(), failureNum);
                    continue;
                }

                try {
                    List<MemberDevice> memberDevices = memberDeviceService.list(new LambdaQueryWrapper<MemberDevice>().eq(MemberDevice::getDeviceId, deviceBase.getId()).ne(MemberDevice::getMemberId, memberUsers.get(0).getId()));
                    List<String> lockDatas = memberDevices.stream().map(MemberDevice::getLockerData).filter(StringUtils::isNotBlank).collect(Collectors.toList());
                    Set<String> lockDataSet = new HashSet<>();
                    for (String lockData : lockDatas) {
                        Collections.addAll(lockDataSet, lockData.split(","));
                    }
                    for (String data : importBean.getLockerData().split(",")) {
                        if (lockDataSet.contains(data)) {
                            throw new ServiceException(500, "格口" + data + "已经被占用！");
                        }
                    }
                } catch (ServiceException e) {
                    addFailMessage(memberImportResultPojoVos, importBean, e.getErrorMessage() + importBean.getMemberJobNum(), failureNum);
                    continue;
                }

                if (StringUtils.isBlank(importBean.getLockerData()) && importBean.getLockerData().split(",").length > deviceBase.getMaxUseNum()) {
                    addFailMessage(memberImportResultPojoVos, importBean, "设备已经超过单人使用最大数量!" + importBean.getMemberJobNum(), failureNum);
                    continue;
                }


                MemberDevice memberDevice = memberDeviceService.getOne(new LambdaQueryWrapper<MemberDevice>().eq(MemberDevice::getMemberId,
                        memberUsers.get(0).getId()).eq(MemberDevice::getDeviceId, deviceBase.getId()));
                if (memberDevice == null) {
                    addFailMessage(memberImportResultPojoVos, importBean, "人员不在白名单中!" + importBean.getMemberJobNum(), failureNum);
                    continue;
                }
                if (!ObjectUtil.equal(memberDevice.getStatus(), 7)) {
                    addFailMessage(memberImportResultPojoVos, importBean, "设备上一次操作结果为 " + MemberDeviceServiceImpl.staus.get(memberDevice.getStatus()) + "  ！" + importBean.getMemberJobNum(), failureNum);
                    continue;
                }

                memberDevice.setLockerData(importBean.getLockerData());
                memberDevice.setStatus(2);
                memberDeviceService.updateById(memberDevice);
                successNum.incrementAndGet();
            } catch (Exception e) {
                log.error("用户【{}】 发生错误 错误信息【{}】", importBean.getMemberJobNum(), ExceptionUtils.getMessage(e));
                addFailMessage(memberImportResultPojoVos, importBean, "发生异常错误!" + ExceptionUtils.getMessage(e), failureNum);
            }
        }

    }

    @Override
    public UserImportResultVO importExcel(MultipartFile file) {
        List<LockerPersonImportBean> visitorImportVOS = PoiUtil.importExcel(file, 0, 1, LockerPersonImportBean.class);
        CopyOnWriteArrayList<MemberImportResultPojoVO> memberImportResultPojoVos = new CopyOnWriteArrayList<>();
        // 保存文件
        sysFileInfoService.uploadFile(file, FileTypeEnum.LOCAL);

        AtomicInteger successNum = new AtomicInteger(0);
        AtomicInteger failureNum = new AtomicInteger(0);

        if (CollectionUtils.isEmpty(visitorImportVOS)) {
            throw new ServiceException(500, "文件中不存在有效数据!");
        }
        long d = System.currentTimeMillis();
        log.info("====导入开始时间==================================================" + DateUtils.formatDate(new Date()));
        if (visitorImportVOS.size() > 20) {
            log.info("开始多线程导入===");
            List<List<LockerPersonImportBean>> splitList = ListUtils.partition(visitorImportVOS, visitorImportVOS.size() / 20);
            CountDownLatch countDownLatch = new CountDownLatch(splitList.size());
            ExecutorService executorService = Executors.newFixedThreadPool(splitList.size());
            for (List<LockerPersonImportBean> oneList : splitList) {
                executorService.execute(() -> {
                    try {
                        signalThreadImport(memberImportResultPojoVos, successNum, failureNum, oneList);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        countDownLatch.countDown();
                    }
                });
            }
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                log.error("线程被其他线程中断【{}】", ExceptionUtil.getMessage(e));
            }
        } else {
            log.info("开始单线程导入===");
            signalThreadImport(memberImportResultPojoVos, successNum, failureNum, visitorImportVOS);
        }
        // 有效数据

        log.info("====导入结束时间==================================================" + (System.currentTimeMillis() - d));
        UserImportResultVO memberImportResultVo = new UserImportResultVO();
        memberImportResultVo.setSuccessNum(successNum.get());
        memberImportResultVo.setFailNum(failureNum.get());
        memberImportResultVo.setMemberImportResultPojoVos(memberImportResultPojoVos);
        return memberImportResultVo;
    }

    @Override
    public void deviceUpdatePush(DeviceBaseParam param) {
        DeviceBase deviceBase = this.getById(param.getId());
        if (ObjectUtil.isNull(deviceBase)) {
            throw new ServiceException(DeviceBaseExceptionEnum.NOT_EXIST);
        }

        try {
            // 通知
            if (ObjectUtil.equals(deviceBase.getDeviceType(), DeviceCategory.SUB_TYPE_STORE + "")) {
                // mqtt通知设备更新
                DwRulesEngine.appVersionService.notice(deviceBase);
            }

        } catch (Exception e) {
            log.warn(e.getMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(DeviceBaseParam deviceBaseParam) {
        String registrationCode = deviceBaseParam.getRegistrationCode();
        List<DeviceBase> list = this.list(new LambdaQueryWrapper<DeviceBase>().ne(DeviceBase::getId, deviceBaseParam.getId())
                .eq(DeviceBase::getRegistrationCode, registrationCode));
        if (!CollectionUtils.isEmpty(list)) {
            throw new ServiceException(500, "注册码重复!");
        }
        DeviceBase deviceBase = this.queryDeviceBase(deviceBaseParam);
        BeanUtil.copyProperties(deviceBaseParam, deviceBase);
        this.updateById(deviceBase);
        publisher.publishEvent(DeviceChangeTypeEnum.EDIT, DeviceSourceEnum.BASE, deviceBase);
    }

    @Override

    public DeviceBase detail(DeviceBaseParam deviceBaseParam) {
        return this.queryDeviceBase(deviceBaseParam);
    }

    @Override
    public PageResult<GetPersonResponse.DataDTO.PersonnelListDTO> listPerson(Long deviceId, String name) {
        DeviceBase deviceBase = this.getById(deviceId);
        if (ObjectUtil.isNull(deviceBase)) {
            throw new ServiceException(DeviceBaseExceptionEnum.NOT_EXIST);
        }
        if (ObjectUtil.equal(deviceBase.getDeviceType(), "1")) {
            return DwRulesEngine.deviceBaseService.listPerson(deviceId, name);
        } else {
            return HQRulesEngine.deviceBaseService.listPerson(deviceId, name);
        }
    }

    /**
     * 获取终端基础属性表
     *
     * @author 胡鹏达
     * @date 2022-07-08 15:24:36
     */
    private DeviceBase queryDeviceBase(DeviceBaseParam deviceBaseParam) {
        DeviceBase deviceBase = this.getById(deviceBaseParam.getId());
        if (ObjectUtil.isNull(deviceBase)) {
            throw new ServiceException(DeviceBaseExceptionEnum.NOT_EXIST);
        }
        return deviceBase;
    }
}
